//@note 上线前的打包
//@author czh
console.time('build');
var less = require('less');
var fs = require('fs');
var browserify = require('browserify');
var ejs = require('ejs');
var path = require('path');
var gulp = require('gulp');
var util = require('gulp-util');
var through = require('through2');
var uglify = require('gulp-uglify');
var minify = require('gulp-minify-css');
var newer = require("gulp-newer");
var webpack = require('webpack');
var gutil = require('gulp-util');
var htmlmin = require('gulp-htmlmin');
var rev = require('gulp-rev');
var revCollector = require('gulp-rev-collector');
var webpackProdConf = require('./bin/build/webpack.prod.conf.js');
var partReleaseRegister = require('./bin/webpackConfigHandler.js');
// var gulpconfig = require('./bin/gulp.config.js');
var gulpsync = require('gulp-sync')(gulp);
// var registerPartRelease = require('./bin/partRelease/src/main');

// 流错误处理
var errStream = function (stream, err) {
    // 输出错误信息
    util.log(err);
    stream.emit('error', err);
    // 结束流
    stream.emit('end');
};

// browserify -> gulp
var getBrowserifyStream = function () {
    var errorJsMsg = function (err) {
        return 'console.log("' + err + '")';
    };

    return through.obj(function (file, env, callback) {

        // browserify解析js
        var b = browserify({
            entries: file.path,
            paths: ['./', './unit/libs']
        });

        var self = this;

        b.bundle(function (err, buffer) {
            if (err) {
                errStream(self, err);
                // browserify解析错误 输出错误信息
                // file.contents=new Buffer(errorJsMsg(err));
                // callback(null,file);
                return;
            }

            file.contents = buffer;
            callback(null, file);
        });
    });
};

// 生成debug文件路径
var parseDebugPath = function (extName, originExtName) {
    return through.obj(function (file, env, callback) {
        // 修改path的扩展名为debug.css或debug.js
        var debugPath = file.path.replace('.' + (originExtName || extName), '.debug.' + extName);
        file.path = debugPath;
        callback(null, file);
    });
};

// 生成线上文件路径
var parsePath = function (extName) {
    return through.obj(function (file, env, callback) {
        // 将path中的debug去掉
        var proPath = file.path.replace('.debug.' + extName, '.' + extName);
        file.path = proPath;
        callback(null, file);
    });
};

var logStream = function (text) {
    return through.obj(function (file, env, callback) {
        // 输出log
        util.log(util.colors.blue(file.relative) + ' ' + text);
        callback(null, file);
    });
};

var getDest = function (src) {
    return src.replace('src/less', 'assets/css')
        .replace('src/js', 'assets/js')
        .replace('demo', 'html')
        .replace(/(\*\*\/)*[^\/]+\.(less|js|html)/, '');
};

var getJsTask = function (src, dest) {
    return gulp.src(src)
    // 任务开始log
        .pipe(logStream('task start'))
        // 使用browserify解析
        .pipe(getBrowserifyStream())
        // 生成debug文件
        .pipe(parseDebugPath('js'))
        .pipe(gulp.dest(dest))
        // 压缩文件 生成线上版本
        .pipe(uglify().on('error', gutil.log))
        .pipe(parsePath('js'))
        .pipe(rev())
        .pipe(gulp.dest(dest))
        // js映射文件保存到./rev/js/ 不merge 两个task同时读写一个文件会出现覆盖问题
        .pipe(rev.manifest())
        .pipe(gulp.dest('./rev/js/'))
        // 任务结束log
        .pipe(logStream('task finish'));
};

var getLessStream = function () {

    // less解析出错时的替换内容
    var errCssMsg = [
        "body:before{",
        "content:'这个文件打包出了问题，请检查相应less文件';",
        "position:fixed;",
        "background:#000;",
        "left:0;top:0;padding:1rem;",
        "}"
    ].join('');

    return through.obj(function (file, env, callback) {

        var self = this;
        var content = file.contents.toString();

        // 使用less解析文件内容
        less.render(content, {
            filename: file.path
        }, function (e, output) {
            if (e) {
                // 错误处理
                errStream(self, e);

                // less解析出错 输出错误提示
                file.contents = new Buffer(errCssMsg, 'utf8');
                callback(null, file);

            } else {
                // 将解析的内容塞到流内
                file.contents = new Buffer(output.css, 'utf8');
                callback(null, file);
            }
        });
    });
};

var getLessTask = function (src, dest) {
    return gulp.src(src)
    // 任务开始log
        .pipe(logStream('task start'))
        // 处理less文件
        .pipe(getLessStream())
        // 生成debug文件
        .pipe(parseDebugPath('css', 'less'))
        .pipe(gulp.dest(dest))
        // 压缩代码
        .pipe(minify())
        // 生成线上代码
        .pipe(parsePath('css'))
        .pipe(rev())
        .pipe(gulp.dest(dest))
        // css映射文件保存到./rev/css/
        .pipe(rev.manifest())
        .pipe(gulp.dest('./rev/css/'))
        // 任务结束log
        .pipe(logStream('task finish'));
};

// ejs -> gulp
var getEjsStream = function () {
    return through.obj(function (file, env, callback) {
        var content = file.contents.toString('utf8');
        try {
            var ejsResult = ejs.render(content, {
                filename: file.path
            });

            // 替换less文件路径 以符合映射表关系
            var result = ejsResult.replace('src/less', 'src/css').replace(/\.less/, '.css');
            file.contents = new Buffer(result, 'utf8');
            callback(null, file);
        } catch (e) {
            // 错误就停止编译
            errStream(this, e);
            callback(e, file);

            // ejs解析出错 先不停止 改造时需要
            // callback(null,file);
        }

    });
};

var getHtmlTask = function (src, dest) {
    return gulp.src(['./rev/**/*.json', src])
    // 开始日志输出
        .pipe(logStream('task start'))
        // ejs解析
        .pipe(getEjsStream())
        // 根据映射关系替换路径
        .pipe(revCollector({
            replaceReved: true, // 已经被替换的文件还能再被替换
            dirReplacements: {
                '/src/css/': '/assets/css',
                '/src/js/': '/assets/js'
            }
        }))
        .pipe(htmlmin({collapseWhitespace: true}))
        // 复制到html目录下
        .pipe(gulp.dest(dest))
        // 结束日志输出
        .pipe(logStream('task finish'));
};

gulp.task('css', function () {
    return getLessTask('./src/less/**/*.less', getDest('./src/less/**/*.less'));
});

gulp.task('js', ['css'], function () {
    return getJsTask('./src/js/**/*.js', getDest('./src/js/**/*.js'));
});

gulp.task('html', ['js'], function () {
    return getHtmlTask('./demo/**/*.html', getDest('./demo/**/*.html'));
});

gulp.task('default', ['webpack:build'], function () {
    console.timeEnd('build');
});

// 生成js/css
gulp.task('webpack', function (callback) {
    webpack(webpackProdConf, function (err, stats) {
        if (err) {
            throw new gutil.PluginError('webpack', err);
        }
        gutil.log('[webpack]', stats.toString({colors: true, chunks: false, children: false}));
        callback();
    });
});

// 依赖打包
partReleaseRegister('part-release', {
    rev: './rev/',
    webpackConfig: webpackProdConf,
    logOpt: {
        logPath: './rev/release_log/',
        domain : 'http://www.zhongliang.com/'
    }
});
gulp.task('webpack:build', gulpsync.sync(['html', 'part-release']), function (callback) {
    // webpack(webpackProdConf, function (err, stats) {
    //     if (err) {
    //         throw new gutil.PluginError('webpack', err);
    //     }
    //     gutil.log('[webpack]', stats.toString({colors: true, chunks: false, children: false}));
    //     callback();
    // });
});

// 老版本提供单个文件打包处理 node gulpfile.js type xxxx.type
if (process.argv[3]) {
    if (process.argv[2] === 'less') {
        getLessTask(process.argv[3], getDest(process.argv[3]));

    } else if (process.argv[2] === 'js') {
        getJsTask(process.argv[3], getDest(process.argv[3]));

    } else if (process.argv[2] === 'html') {
        getHtmlTask(process.argv[3], getDest(process.argv[3]));
    }
}

// 老版本分业务打包
// gulpconfig.forEach(function (task) {
//     var lastTaskType = '';
//
//     // less、js、html编译任务
//     ['less', 'js', 'html'].forEach(function (type, index, arr) {
//         var getTaskFunc = type === 'less' ? getLessTask : (type === 'js' ? getJsTask : getHtmlTask);
//         var nowTaskName = type + '_' + task.taskname;
//         var nowTaskFile = task.source[type];
//         var preTaskName = arr[index - 1] + '_' + task.taskname;
//         var preTaskFile = task.source[arr[index - 1]];
//
//         if (index === 2 && !preTaskFile) {
//             preTaskName = arr[index - 2] + '_' + task.taskname;
//             preTaskFile = task.source[arr[index - 2]];
//         }
//
//         if (nowTaskFile) {
//             lastTaskType = type;
//             gulp.task(nowTaskName, preTaskFile ? [preTaskName] : [], function () {
//                 return getTaskFunc(task.source[type], getDest(task.source[type]));
//             });
//         }
//     });
//
//     // 最终这个业务的编译任务
//     gulp.task(task.taskname, lastTaskType ? [lastTaskType + '_' + task.taskname] : [], function () {
//         console.timeEnd('build');
//     });
// });

// registerPartRelease('part');
